home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 25
/
Aminet 25 (1998)(GTI - Schatztruhe)[!][Jun 1998].iso
/
Aminet
/
util
/
pack
/
xpk_Source.lha
/
xpk_Source
/
libraries
/
FAST
/
compress2.a
< prev
next >
Wrap
Text File
|
1998-02-08
|
6KB
|
282 lines
; XDEF compress_slow
;On entry:
; a0 = InBuf
; a1 = OutBuf
; a2 = HashTab
; d0 = InLen
compress_slow:
movem.l a3-a6/d1-d7,-(sp)
move.l a0,d1 ; d1=src+src_len+2
add.l d0,d1 ; since all srcpointers are
addq.l #2,d1 ; 2 to big we need this +2 !
moveq.l #$FFFFFFFC,d2
and.l d0,d2
add.l a1,d2
move.l d2,a4 ; a4=dst+(src_len & ~3)
movem.l a1/a4,-(sp) ; save dst and dst_end for later use
;;; lea $40000(a2),a6 ; a6=hh a6-$40000 == hash
moveq.l #4,d0
swap d0
move.l a2,a6
add.l d0,a6
lea.l -4096(a0),a5
move.w #$10FF,d2
hfill: move.l a5,(a2)+ ; fill hash with src-4096
move.l a5,(a2)+ ; hash is $1100*$10 = $11000 longs big
move.l a5,(a2)+
move.l a5,(a2)+
move.l a5,(a2)+
move.l a5,(a2)+
move.l a5,(a2)+
move.l a5,(a2)+
move.l a5,(a2)+
move.l a5,(a2)+
move.l a5,(a2)+
move.l a5,(a2)+
move.l a5,(a2)+
move.l a5,(a2)+
move.l a5,(a2)+
move.l a5,(a2)+
dbra d2,hfill
moveq.l #-1,d0 ; d0 = 4*hash_fkt(s,s+1,s+2)
move.b (a0)+,d0 ; a0 += 2
lsl.w #8,d0
move.b (a0)+,d0
add.b (a0),d0
lsl.l #2,d0
move.l a0,0(a6,d0.l) ; hash[hash_val]=s
move.l #$00000FFF,d4
subq.l #2,a4
move.l a4,a3 ; get place to put next ctrl_word
moveq.l #1,d7 ; initialize ctrl_word with $0001
move.l a0,d2
sub.l d4,d2 ; d2 = src - 4095
; bra.s do_literal2 ; The first one is always a literal.
;REGISTER MAP
;============
; a0 source
; a1 destination byte stream (post increment)
; a2 Temporary
; a3 place to put control word in output
; a4 destination word stream (pre decrement)
; a5 Temporary
; a6 hashtable
; a7 Stack pointer. Don't touch!
; d0 Temporary
; d1 End of input+2
; d2 src - 4095
; d3 match_offset , match_len
; d4 Constant 4095
; d5 work pointer into LZ77-window
; d6 Temporary
; d7 Buffers the current control word.
;;;---------------------------------------------------------------------------
do_literal2:
move.b -2(a0),(a1)+ ; write literal
moveq.l #-1,d0 ; increment src
move.b -1(a0),d0
lsl.w #8,d0
move.b (a0)+,d0 ; ++a0
addq.l #1,d2 ; d2+=1 d2==src-4095
add.b (a0),d0
lsl.l #2,d0 ; d0 = hash_fkt(src[-2],src[-1],src[0])
move.l 0(a6,d0.l),d5 ; d5 = wrk = hash[hash_val]
move.l a0,0(a6,d0.l) ; hash[hash_val] = src
move.w a0,d0
and.w d4,d0
asl.w #2,d0 ; clears X
move.l d5,0(a6,d0.w) ; hh[src&$FFF] = [old]hash[hash_val] {== wrk}
insctl: addx.w d7,d7 ; inject X-Flag into ctrl_word
bcc.s eloop ; control not full
move.w d7,(a3) ; write ctrl_word to it's place
subq.l #2,a4
move.l a4,a3 ; get place to put next ctrl_word
moveq.l #1,d7 ; initialize ctrl_word with $0001
cmp.l d1,a0 ; Has src reached src_end?
bcc end_control_done
eloop: cmp.l d2,d5 ; is wrk below the limit
bmi.s do_literal2 ; is wrk < src - 4095
moveq.l #1,d3 ; Initializations for iloop
; match_ofs,match_len-1 = 0,1
iloop: move.l a0,a2
move.l d5,a5
MATCH MACRO
cmp.b (a2)+,(a5)+
bne.s \1
ENDM
MATCH next ; 2
MATCH mism ; 3
MATCH mism ; 4
MATCH mism ; 5
MATCH mism ; 6
MATCH mism ; 7
MATCH mism ; 8
MATCH mism ; 9
MATCH mism ;10
MATCH mism ;11
MATCH mism ;12
MATCH mism ;13
MATCH mism ;14
MATCH mism ;15
MATCH mism ;16
MATCH mism ;17
addq.l #1,a5 ;18
mism: sub.l d5,a5 ; a5=match_len-1
cmp.w a5,d3
bcc.s next ; new match is not longer than old one
move.w a0,d3
sub.w d5,d3 ; d3 = src - wrk = match_ofs
swap d3
move.w a5,d3 ; match_ofs,match_len-1 is updated.
cmp.b #17,d3
bcc.s docopy ; match_len-1 >= 18-1
next: and.w d4,d5 ; d5=wrk & $00000FFF
lsl.w #2,d5
move.l 0(a6,d5.w),d5 ; wrk=hh[wrk & $00000FFF]
cmp.l d2,d5 ; is wrk in range?
bcc.s iloop ; is wrk >= src - 4095 ?
finished_chain:
cmp.b #2,d3
bcs do_literal2
docopy: moveq.l #17,d0
add.l d0,d2
sub.b d3,d0 ; d0=17-(match_len-1)
sub.l d0,d2
addq.l #1,d2 ; d2+=match_len
swap d3
asl.w #4,d3
or.b d0,d3 ; d3 = OOOOOOOO OOOOLLLL
move.w d3,-(a4) ; write copyinfo
swap d3 ; d3.w = match_len - 1
incsrc: moveq.l #-1,d0 ; increment src
move.b -1(a0),d0
lsl.w #8,d0
move.b (a0)+,d0
add.b (a0),d0 ; ++a0
move.w a0,d6
and.w d4,d6
asl.w #2,d6
asl.l #2,d0 ; d0 = hash_fkt(src[-2],src[-1],src[0])
; Does set the X-Flag
move.l 0(a6,d0.l),d5 ; d5 = wrk = hash[hash_val]
move.l a0,0(a6,d0.l) ; hash[hash_val] = src
move.l d5,0(a6,d6.w) ; hh[src&$FFF] = [old]hash[hash_val] {== wrk}
dbra d3,incsrc
cmp.l d1,a0 ; Has src reached src_end?
bcs insctl ; Insert the X-Flag[=1] into control
;;;The main loop ends here.
;;;---------------------------------------------------------------------------
;FINALIZATION
;============
add.l d0,d0 ; Just set the Carry [d0 is junked]
; Fill the rest of the control. Since the carry is set the 1st control
; inserted will be a copy item and the rest literals.
FillControl:
addx.w d7,d7
bcc.s FillControl
move.w d7,(a3) ;Write it to its output position
subq.l #2,a4 ; reserve space for next controlword
end_control_done:
addq.l #2,a4 ; Junk new controlword
movem.l (sp)+,d6/d7 ; Pop dst and dst_end
;Copy the literals after the word stream pointed to by a1.
move.l a4,d0 ;d0:=Number of Bytes to increase a1
sub.l a1,d0 ;till a1 and a4 are equally aligned.
bcc.s did_compress
;byte- and wordstream together do exceede the size of the output buffer.
moveq #0,d0 ; return 0 to indicate overrun
bra.s finish2
did_compress:
moveq #3,d1
and.w d0,d1
moveq.l #0,d0 ;pad a1 up to make a1 and a4 equally aligned.
bra.s EFLoop2
FLoop2: move.b d0,(a1)+
EFLoop2: dbra d1,FLoop2
sub.l a4,d7 ;d7:=size of wordstream
lsr.l #2,d7
bcc.s NoWord2
move.w (a4)+,(a1)+
NoWord2: lsr.l #1,d7
bcc.s NoLong2
move.l (a4)+,(a1)+
NoLong2 lsr.l #1,d7
bcc.s NoQuad2
move.l (a4)+,(a1)+
move.l (a4)+,(a1)+
NoQuad2 lsr.l #1,d7
bcc.s ECLoop2
bra.s MCLoop2
CLoopH2 swap d7
CLoop2: move.l (a4)+,(a1)+
move.l (a4)+,(a1)+
move.l (a4)+,(a1)+
move.l (a4)+,(a1)+
MCLoop2 move.l (a4)+,(a1)+
move.l (a4)+,(a1)+
move.l (a4)+,(a1)+
move.l (a4)+,(a1)+
ECLoop2 dbra d7,CLoop2
swap d7
dbra d7,CLoopH2
move.l a1,d0
sub.l d6,d0 ;d0:=Final output length
finish2: movem.l (sp)+,a3-a6/d1-d7
rts